package com.jy.modules.cims.creditright.service;

import java.math.BigDecimal;
import java.sql.Timestamp;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.jy.modules.cims.common.CimsConstant;
import com.jy.modules.cims.common.CimsIrtUrlConstant;
import com.jy.modules.cims.common.JResult;
import com.jy.modules.cims.common.exception.CimsException;
import com.jy.modules.cims.common.sysUtils.CollectionsUtils;
import com.jy.modules.cims.common.sysUtils.DateTimeUtils;
import com.jy.modules.cims.common.sysUtils.SearchParamUtil;
import com.jy.modules.cims.common.sysUtils.SimpleStringUtils;
import com.jy.modules.cims.component.balance.SettleUtilsService;
import com.jy.modules.cims.component.common.service.TCMmCostPlanService;
import com.jy.modules.cims.component.creditRight.plan.CreditPlanConstant;
import com.jy.modules.cims.data.common.dao.TCMmContractDao;
import com.jy.modules.cims.data.common.dto.TCMmContractDTO;
import com.jy.modules.cims.data.common.dto.TCMmCostAffiliationDTO;
import com.jy.modules.cims.data.common.dto.TCMmCostPlanDTO;
import com.jy.modules.cims.data.common.dto.TCMmCreditDealDetailDTO;
import com.jy.modules.cims.data.dao.CostPlanDao;
import com.jy.modules.cims.data.dao.CreditRightDao;
import com.jy.modules.cims.data.dto.CreditDetailDto;
import com.jy.modules.cims.data.dto.CreditDetailQueryDto;
import com.jy.modules.cims.data.dto.DealDto;
import com.jy.modules.cims.data.dto.credit.CostAffiliationResultDto;
import com.jy.modules.cims.data.dto.credit.CreditRedeemSettleDto;
import com.jy.modules.cims.data.dto.credit.CreditSettleInfoDto;
import com.jy.modules.cims.data.dto.credit.CreditVrMonthRepayDto;
import com.jy.modules.cims.data.dto.credit.PublicSettleParamDto;
import com.jy.modules.cims.data.dto.credit.PublicSettleResultDto;
import com.jy.modules.cims.deal.service.DealService;
import com.jy.modules.cims.interact.ICInteract;
import com.jy.modules.cims.sysassist.SysAssistService;
import com.jy.platform.api.org.SessionAPI;
import com.jy.platform.api.org.UserInfo;

/**
 * @description 结算债权业务服务层。
 * @author shengzhoutao
 * @date 2015-01-07 16:21:57
 */
@Service("com.jy.modules.cims.creditright.service.SettleCreditService")
public class SettleCreditService {
	private static final Logger logger = LoggerFactory.getLogger(SettleCreditService.class);
	
	@Autowired
	private TCMmContractDao tcmmContractDao;

	@Autowired
	private CreditRightDao creditRightDao;

	@Autowired
	private CostPlanDao costPlanDao;

	@Autowired
	private SessionAPI sessionAPI;

	@Autowired
	@Qualifier("com.jy.modules.cims.creditright.service.CreditRightService")
	private CreditRightService creditRightService;

	@Autowired
	@Qualifier("com.jy.modules.cims.deal.service.DealService")
	public DealService dealService;

	@Autowired
	@Qualifier("com.jy.modules.cims.component.balance.SettleUtilsService")
	public SettleUtilsService settleUtilsService;

	@Autowired
	@Qualifier("com.jy.modules.cims.sysassist.SysAssistService")
	private SysAssistService sysAssistService;

	@Autowired
	@Qualifier("com.jy.modules.cims.interact.CCInteractImpl")
	private ICInteract iCInteract;

	@Autowired
	@Qualifier("com.jy.modules.cims.creditright.service.SettleAndSecondBuyService")
	public SettleAndSecondBuyService settleAndSecondBuyService;
	
	@Autowired
	@Qualifier("com.jy.modules.cims.component.common.service.TCMmCostPlanService")
	public TCMmCostPlanService tcmmCostPlanService;

	/**
	 * @description 正常结算/异常结算，新建结算，债权列表展示调用该方法。 <br>
	 *              按照输入页面输入合作机构编号、债权包编号条件，分页查询所有符合结算的债权明细 。 <br>
	 * @author shengzhoutao
	 * @param searchParams
	 *            参数，dto的存放对象为CreditDetailQueryDto
	 * @return List<CreditDetailDto> 债权明细
	 */
	public List<CreditDetailDto> searchCreditDetailForSettleByPaging(Map<String, Object> searchParams) {
		logger.info("=======正常结算/异常结算，新建结算，债权列表展示=======");

		CreditDetailQueryDto creditDetailQueryDto = (CreditDetailQueryDto) searchParams.get("dto");

		// 验证输入的结算参数
		checkSettleParams(creditDetailQueryDto);

		searchParams.put("dto", creditDetailQueryDto);
		return creditRightDao.searchCreditDetailForSettleByPaging(searchParams);
	}

	/**
	 * @description 正常结算/异常结算，新建结算，债权列表展示调用该方法。 <br>
	 *              按照输入页面输入合作机构编号、债权包编号条件，不分页查询所有符合结算的债权明细 。 <br>
	 * @author shengzhoutao
	 * @param searchParams
	 *            参数，dto的存放对象为CreditDetailQueryDto
	 * @return List<CreditDetailDto> 债权明细
	 */
	public List<CreditDetailDto> searchCreditDetailForSettle(Map<String, Object> searchParams) {
		logger.info("=======正常结算/异常结算，新建结算，债权列表展示=======");

		CreditDetailQueryDto creditDetailQueryDto = (CreditDetailQueryDto) searchParams.get("dto");

		return searchCreditDetailForSettle(creditDetailQueryDto);
	}

	/**
	 * @description 正常结算/异常结算，新建结算，债权列表展示调用该方法。 <br>
	 *              按照输入页面输入合作机构编号、债权包编号条件，不分页查询所有符合结算的债权明细 。 <br>
	 * @author shengzhoutao
	 * @param dto
	 *            合作机构编号、债权包编号
	 * @return List<SettleDto> 债权明细
	 */
	public List<CreditDetailDto> searchCreditDetailForSettle(CreditDetailQueryDto dto) {
		logger.info("=======正常结算/异常结算，新建结算，不分页查询可结算的债权=======");

		// 验证输入的结算参数
		checkSettleParams(dto);

		List<CreditDetailDto> creditDetailList = creditRightDao.searchCreditDetailForSettle(SearchParamUtil.getSearchParam(dto));

		if (dto.isTranFlag() && CollectionsUtils.isNotEmpty(creditDetailList)) {
			creditDetailList = tranCreditDetailList(creditDetailList);
		}

		return creditDetailList;
	}

	/**
	 * @description 根据流水号查询债权列表(已经结算) <br>
	 * @author shengzhoutao
	 * @param searchParams
	 *            参数，dto的存放对象为DealDto,
	 * @return List<CreditDetailDto> 债权明细
	 */
	public List<CreditDetailDto> searchCreditDetailForSettleByDealCode(Map<String, Object> searchParams) {
		logger.info("=======根据流水号查询债权列表(已经结算)调用该方法=======");

		List<CreditDetailDto> creditDetailList = dealService.getDealDetailByCreditList(searchParams);
		if (CollectionsUtils.isEmpty(creditDetailList)) {
			return null;
		}

		DealDto deal = (DealDto) searchParams.get("dto");
		List<TCMmCostPlanDTO> costPlanList = searchCostPlanByDealCode(deal.getDealCode());
		if (CollectionsUtils.isEmpty(costPlanList)) {
			return creditDetailList;
		} else {
			return tranCreditDetailList(creditDetailList, costPlanList);
		}
	}

	/**
	 * @description 正常结算/异常结算结算信息的显示调用该方法。 <br>
	 *              按照输入条件统计待结算的债权明细，返回债权结算信息对象实体的字段如下 ：<br>
	 *              结算金额 ：<code>thisRepaySum</code>；<br>
	 *              需匹配金额：<code>matchAmount</code>；<br>
	 *              返还金额：<code>returnAmount</code>；<br>
	 *              债权记录条数：<code>creditRow</code>；<br>
	 *              实际匹配金额 ： <code>practicalAmount</code>；
	 * @author shengzhoutao
	 * @param queryDto
	 *            合作机构编号、债权包编号、合约编码、结算日期
	 * @return 债权结算信息对象实体
	 */
	public CreditSettleInfoDto statCreditDetailForSettle(CreditDetailQueryDto queryDto) {
		logger.info("=======正常结算/异常结算结算信息的显示调用该方法=======");

		CreditSettleInfoDto settleInfo = new CreditSettleInfoDto();

		// 验证输入的结算参数
		checkSettleParams(queryDto);

		int creditRow = creditRightDao.getCreditDetailRowsForSettle(SearchParamUtil.getSearchParam(queryDto)).intValue();
		if (creditRow == 0) {
			return settleInfo;
		}

		settleInfo = statCostPlanForSettle(queryDto);
		settleInfo.setCreditRow(creditRow);// 债权记录条数

		return settleInfo;
	}

	private CreditSettleInfoDto statCostPlanForSettle(CreditDetailQueryDto queryDto) {
		CreditSettleInfoDto creditSettleInfo = new CreditSettleInfoDto();
		TCMmCostPlanDTO costPlanDTO = creditRightService.statCostPlanForSettle(queryDto);
		if (null == costPlanDTO) {
			return creditSettleInfo;
		}

		if (null != costPlanDTO.getThisRepaySum()) {
			creditSettleInfo.setThisRepaySum(costPlanDTO.getThisRepaySum());// 结算金额
		} else {
			BigDecimal mustAmount = costPlanDTO.getMustAmount();
			mustAmount = mustAmount.add(costPlanDTO.getMustAccrual());
			creditSettleInfo.setThisRepaySum(mustAmount);// 结算金额
		}
		creditSettleInfo.setMustAmount(costPlanDTO.getMustAmount() == null ? BigDecimal.ZERO : costPlanDTO.getMustAmount());// 应还本
		creditSettleInfo.setMustAccrual(costPlanDTO.getMustAccrual() == null ? BigDecimal.ZERO : costPlanDTO.getMustAccrual());// 应还息
		creditSettleInfo.setMatchAmount(costPlanDTO.getMatchAmount() == null ? BigDecimal.ZERO : costPlanDTO.getMatchAmount());// 需匹配金额
		creditSettleInfo.setReturnAmount(costPlanDTO.getReturnAmount() == null ? BigDecimal.ZERO : costPlanDTO.getReturnAmount());// 返还金额
		creditSettleInfo.setPracticalAmount(costPlanDTO.getMatchAmount() == null ? BigDecimal.ZERO : costPlanDTO.getMatchAmount());// 实际匹配金额默认等于需匹配金额

		return creditSettleInfo;
	}

	/**
	 * @description 根据流水号查询还款计划(已经结算)
	 * @author shengzhoutao
	 * @param dealCode
	 * @return
	 */
	public List<TCMmCostPlanDTO> searchCostPlanByDealCode(final String dealCode) {
		if (!SimpleStringUtils.hasText(dealCode)) {
			return null;
		}

		CreditDetailQueryDto dto = new CreditDetailQueryDto();
		dto.setDealCode(dealCode);

		return costPlanDao.searchCostPlanByDealCode(SearchParamUtil.getSearchParam(dto));
	}

	/**
	 * @description 正常结算/异常结算保存调用该方法。 <br>
	 *              按照输入条件查询债权明细和结算计划，将查询结果生成新合作机构交易流水表，并对相关值更新。 <br>
	 *               <br>
	 * @author shengzhoutao
	 * @param params
	 *            输入值必须包含: <br>
	 *            交易类型<code>dealType</code>
	 *            :10-债权转让正常结算,11-债权转让异常结算,12-贷款转出正常结算,13-贷款转出异常结算,15-债权受让正常结算;<br>
	 *            合作机构编号<code>cooperorgCode</code>,该字段必须输入;<br>
	 *            合约编号<code>contractCode</code>,该字段必须输入;<br>
	 *            债权包编号 <code>packageNum</code>,该字段必须输入;<br>
	 *            协议编号 <code>agreementCode</code>;<br>
	 *            结算日期 <code>settleDate</code>,该字段必须输入;<br>
	 *            实售金额 <code>practicalSellSum</code>;<br>
	 *            异常类型/还款状态 <code>planStatus</code>,异常结算该字段必须输入;<br>
	 * @return dealCode 新增的交易流水号
	 * @throws Exception
	 */
	public String doSettle(CreditDetailQueryDto params) throws Exception {
		logger.info("=======正常结算/异常结算保存调用该方法=======");

		// 验证输入的结算参数
		checkSettleParams(params);

		// 按照输入页面输入结算计划，还款计划，贷款明细，债权包信息等条件查询所有符合条件债权明细。
		List<CreditDetailDto> creditDetailList = searchCreditDetailForSettle(params);//
		if (CollectionsUtils.isEmpty(creditDetailList)) {
			throw new CimsException(MessageFormat.format("根据合作机构编号[{0}]、所属包编号[{1}]、合约编号[{2}]条件没有查询到符合条件债权明细！",
					new Object[] { params.getCooperorgCode(), params.getPackageNum(), params.getContractCode() }));
		}

		// 按照输入条件统计待结算的债权明细，返回债权结算信息
		CreditSettleInfoDto creditSettleInfoDto = statCostPlanForSettle(params);
		creditSettleInfoDto.setCreditRow(creditDetailList.size());

		// 生成交易流水号
		String dealCode = sysAssistService.getBizNoForNewTran(CimsConstant.BIZNO_TYPE_DEAL);
		params.setDealCode(dealCode);

		// 批量新增债权交易明细
		List<TCMmCreditDealDetailDTO> creditDealDetailList = getCreditDealDetailList(creditDetailList, params);
		creditRightService.insertCreditDealDetail(creditDealDetailList);

		// 批量修改债权明细的剩余还款期数(等于该债权的结算计划的剩余未结算的总期数)
		creditRightService.updateCreditDetailResidueRepayPeriodForSettle(params);

		// 批量修改结算计划表的结算状态
		creditRightService.updateCostPlanStatusForSettle(params);

		// 定时任务自动处理，实售金额=应匹配金额
		if (params.isBatchFlag()) {
			params.setPracticalSellSum(creditSettleInfoDto.getMatchAmount());
		}

		// 新增合作机构交易流水表
		DealDto dealDto = getDealDto(creditDetailList, params, creditSettleInfoDto);
		dealService.saveDeal(dealDto);

		// 批量修改债权明细状态，债权已结算：条件是该债权所有的期数的结算计划已经结算完成
		// 或者是异常结算(11-债权转让异常结算;13-贷款转出异常结算;16-债权受让异常结算)提前结清，合约还款计划变更类型类型:2-提前结清，违约处理方式:01-提前结清.
		params.setCreditorStatus(CimsConstant.CREDIT_STATUS_END);
		creditRightService.updateCreditDetailStatusForSettle(params, creditDetailList);

		return dealCode;
	}

	/**
	 * @description 确认月还结算(给现金)
	 *              全额返还的本+息和本息匹配的息，走现金结算
	 * @param creditDetailList
	 * @throws Exception
	 */
	public void doConfirm(List<CreditDetailDto> creditDetailList) throws Exception {
		if (CollectionsUtils.isEmpty(creditDetailList)) {
			return;
		}

		List<CreditVrMonthRepayDto> virtualRepayList = new ArrayList<CreditVrMonthRepayDto>();// 虚拟月还债权列表
		List<CreditVrMonthRepayDto> cashRepayList = new ArrayList<CreditVrMonthRepayDto>();// 月还现金结算列表
		List<CreditRedeemSettleDto> settleList = new ArrayList<CreditRedeemSettleDto>();// 结清债权列表
		CreditVrMonthRepayDto creditVrMonthRepayDto = null;
		CreditRedeemSettleDto creditRedeemSettleDto = null;

		TCMmCostAffiliationDTO costAffiliation = new TCMmCostAffiliationDTO();
		costAffiliation.setCooperorgCode(creditDetailList.get(0).getCooperorgCode());
		costAffiliation.setBusinessScenarios(CimsConstant.CREDIT_SOURCE_LOA.equals(creditDetailList.get(0).getCreditSource())?CimsConstant.DEAL_TYPE_LOAN_CREDIT_SETTLE:CimsConstant.DEAL_TYPE_CREDIT_SETTLE);//月还结算
		CostAffiliationResultDto costAffiliationResult = settleUtilsService.checkCost(costAffiliation);
		for (CreditDetailDto creditDetailDto : creditDetailList) {
			creditVrMonthRepayDto = new CreditVrMonthRepayDto();
			creditVrMonthRepayDto.setDealCode(creditDetailDto.getDealCode());// 交易流水号
			creditVrMonthRepayDto.setTransferId(creditDetailDto.getTransferId());// 债权转让编号
			creditVrMonthRepayDto.setEachRepaymentValue(creditDetailDto.getThisRepaySum());// 合作机构要求月还
			creditVrMonthRepayDto.setEachRepaymentPeriods(Integer.parseInt(creditDetailDto.getCurrentTime().toString()));// 月还期数
			creditVrMonthRepayDto.setCurRepayDate(creditDetailDto.getSettleDate());// 月还日期

			creditDetailDto.setDisposeType(creditDetailDto.getDisposeType() == null ? "" : creditDetailDto.getDisposeType());
			if ((CreditPlanConstant.DEAL_MODE_VIRUALCASH.equals(creditDetailDto.getDisposeType().trim()))
					|| (CreditPlanConstant.DEAL_MODE_NORMAL.equals(creditDetailDto.getDisposeType().trim()))) {
				creditDetailDto.setInferfaceNo(creditDetailDto.getInferfaceNo() == null ? "" : creditDetailDto.getInferfaceNo());
				if (!CimsIrtUrlConstant.IRT_CREDIT_VR_GZ_TO_CORE.equals(creditDetailDto.getInferfaceNo())) {
					// 虚拟月还债权列表
					virtualRepayList.add(creditVrMonthRepayDto);
				}

				creditVrMonthRepayDto.setIsVirtualRepay("1");// 是否虚拟月还:1-虚拟月还
			} else {
				creditVrMonthRepayDto.setIsVirtualRepay("0");// 是否虚拟月还:0-正常月还
			}

			// 结清债权列表
			String planStatus = creditDetailDto.getPlanStatus() == null ? "" : creditDetailDto.getPlanStatus();
			if (CreditPlanConstant.CHANGE_TYPE_ADVANCEFINISH.equals(planStatus) 
					|| CreditPlanConstant.CHANGE_TYPE_ROLLFINISH.equals(planStatus)
					|| CreditPlanConstant.CHANGE_TYPE_ANEW.equals(planStatus)
					|| CreditPlanConstant.CHANGE_TYPE_CHANGEDATE.equals(planStatus)
					|| CreditPlanConstant.CHANGE_TYPE_FORCEFINISH.equals(planStatus)) {// 当PlanStatus有值的时候提前结清
				creditRedeemSettleDto = new CreditRedeemSettleDto();
				creditRedeemSettleDto.setTransferId(creditDetailDto.getTransferId());// 债权转让编号
				creditRedeemSettleDto.setDealCode(creditDetailDto.getDealCode());// 交易流水号
				creditRedeemSettleDto.setTotalSettleValue(creditDetailDto.getReturnAmount().add(creditDetailDto.getMatchAmount()));//合作机构要求总结清价值
				creditRedeemSettleDto.setSettleCreditorValue(creditDetailDto.getReturnAmount());// 合作机构要求结清价值
				creditRedeemSettleDto.setServiceCharge(costAffiliationResult.isServiceFee() ? creditDetailDto.getBackFee() : BigDecimal.ZERO);// 服务费
				creditRedeemSettleDto.setCashDeposit(BigDecimal.ZERO);// 保证金
				creditRedeemSettleDto.setGuaranteeFee(BigDecimal.ZERO);// 担保费

				settleList.add(creditRedeemSettleDto);
			} else {
				// 转让债权月还现金结算列表
				creditVrMonthRepayDto.setContractNo(creditDetailDto.getCreditCode());// 合同编号
				creditVrMonthRepayDto.setCashSum(creditDetailDto.getReturnAmount());// 结算现金金额
				if(creditVrMonthRepayDto.getCashSum().compareTo(creditVrMonthRepayDto.getEachRepaymentValue())>0){
					creditVrMonthRepayDto.setEachRepaymentValue(creditVrMonthRepayDto.getCashSum());
				}
				cashRepayList.add(creditVrMonthRepayDto);
			}
		}
		
		UserInfo userInfo = sessionAPI.getCurrentUserInfo();
		PublicSettleParamDto publicSettleParamDto = new PublicSettleParamDto();
		publicSettleParamDto.setCCode(creditDetailList.get(0).getCooperorgCode());
		publicSettleParamDto.setApplyName(userInfo != null ? userInfo.getUserName().toString() : "管理员");// 创建人
		publicSettleParamDto.setBizType(CimsConstant.CREDIT_SOURCE_LOA.equals(creditDetailList.get(0).getCreditSource()) ? "3" : "2");

		// 虚拟现金流挂账
		if (CollectionsUtils.isNotEmpty(virtualRepayList)) {
			publicSettleParamDto.setListVrMonthRepay(virtualRepayList);
			
			doVRMonth(publicSettleParamDto);
		}

		// 月还现金结算
		if (CollectionsUtils.isNotEmpty(cashRepayList)) {
			String dealCode = sysAssistService.getBizNoForNewTran(CimsConstant.BIZNO_TYPE_SETTLE);// 流水号
			publicSettleParamDto.setApplyCode(dealCode);
			publicSettleParamDto.setListVrMonthRepay(cashRepayList);
			
			doMonthCashRepay(publicSettleParamDto);
		}

		// 结清债权现金结算
		if (CollectionsUtils.isNotEmpty(settleList)) {
			String dealCode = sysAssistService.getBizNoForNewTran(CimsConstant.BIZNO_TYPE_SETTLE);// 流水号
			publicSettleParamDto.setApplyCode(dealCode);
			publicSettleParamDto.setListRedeemSettle(settleList);
			
			doCashSettle(publicSettleParamDto);
		}
	}

	/**
	 * @description 根据交易流水号删除月还交易(同时适合删除二次购买)
	 * @param dealCode
	 *            交易流水号
	 * @return 返回结果值(true:成功;false:失败)
	 * @throws Exception
	 */
	public JResult doDeleteSettle(String dealCode) throws Exception {
		JResult result = new JResult();
		result.setSuccess(false);

		List<DealDto> dealDtoList = dealService.getCooperorgDealByDealCodeStr(dealCode);
		if (CollectionsUtils.isEmpty(dealDtoList)) {
			result.setErrMsg(MessageFormat.format("根据交易流水号[{0}]没有查询到该信息！", new Object[] { dealCode }));
			return result;
		}

		DealDto dealDto = dealDtoList.get(0);
		if (CimsConstant.DEAL_TYPE_MONTH_BACK.equals(dealDto.getDealType()) || CimsConstant.DEAL_TYPE_CREDIT_SETTLE.equals(dealDto.getDealType())
				|| CimsConstant.DEAL_TYPE_LOAN_MONTH_BACK.equals(dealDto.getDealType())
				|| CimsConstant.DEAL_TYPE_LOAN_CREDIT_SETTLE.equals(dealDto.getDealType())
				|| CimsConstant.DEAL_TYPE_CREDIT_NORMAL_SETTLE_REC.equals(dealDto.getDealType())
				|| CimsConstant.DEAL_TYPE_CREDIT_ABNORMAL_SETTLE_REC.equals(dealDto.getDealType())) {
			logger.info("删除月还记录==>>");
			settleAndSecondBuyService.deleteSettle(dealCode);
		} else if (CimsConstant.DEAL_TYPE_SECOND_PURCHASE.equals(dealDto.getDealType())) { // 二次购买
			logger.info("删除二次购买和月还记录==>>");
			settleAndSecondBuyService.deleteSecondBuy(dealCode);
		} else {
			result.setErrMsg(MessageFormat.format("交易流水号[{0}]的交易类型不符合要求！", new Object[] { dealCode }));
			return result;
		}

		result.setSuccess(true);
		return result;
	}

	// ////////////////////////////////////////////
	
	/**
	 * @description 虚拟现金流挂账
	 * @param publicSettleParamDto
	 */
	public void doVRMonth(PublicSettleParamDto publicSettleParamDto) {
		PublicSettleResultDto publicSettleResultDto = iCInteract.sendVRMonthGz(publicSettleParamDto);
		boolean remoteInvocation = getRemoteInvocationResult(publicSettleResultDto);
		if (!remoteInvocation) {
			// 调用接口处理失败
			return;
		}

		CreditDetailDto updateCreditDetailDto = null;
		List<CreditDetailDto> updateList = new ArrayList<CreditDetailDto>();
		List<CreditVrMonthRepayDto> virtualRepayList = publicSettleParamDto.getListVrMonthRepay();
		for (CreditVrMonthRepayDto dto : virtualRepayList) {
			updateCreditDetailDto = new CreditDetailDto();
			updateCreditDetailDto.setDealCode(dto.getDealCode());
			updateCreditDetailDto.setTransferId(dto.getTransferId());
			updateCreditDetailDto.setInferfaceNo(CimsIrtUrlConstant.IRT_CREDIT_VR_GZ_TO_CORE);

			updateList.add(updateCreditDetailDto);
		}

		// 标出该条已经做过虚拟现金流挂账
		stampCreditDetailInferfaceNo(updateList);
	}

	/**
	 * @description 债权转让月还现金结算
	 * @param publicSettleParamDto
	 * @throws Exception
	 */
	public void doMonthCashRepay(PublicSettleParamDto publicSettleParamDto) throws Exception {
		PublicSettleResultDto publicSettleResultDto = iCInteract.sendMonthCashRepay(publicSettleParamDto);
		boolean remoteInvocation = getRemoteInvocationResult(publicSettleResultDto);
		if (!remoteInvocation) {
			// 调用接口处理失败
			return;
		}

		CreditDetailDto updateCreditDetailDto = null;
		List<CreditDetailDto> updateList = new ArrayList<CreditDetailDto>();
		List<CreditVrMonthRepayDto> cashRepayList = publicSettleParamDto.getListVrMonthRepay();
		for (CreditVrMonthRepayDto dto : cashRepayList) {
			updateCreditDetailDto = new CreditDetailDto();
			updateCreditDetailDto.setDealCode(dto.getDealCode());
			updateCreditDetailDto.setTransferId(dto.getTransferId());
			updateCreditDetailDto.setSettleApplyId(publicSettleParamDto.getApplyCode());
			updateCreditDetailDto.setCostState(CimsConstant.COST_STATUS_SQ);

			updateList.add(updateCreditDetailDto);
		}

		// 修改流水表结算状态和申请编号
		if (CollectionsUtils.isNotEmpty(updateList)) {
			creditRightDao.updateCreditDetailCostInfo(updateList);
		}
	}
	
	/**
	 * @description 月还现金结算
	 * @param publicSettleParamDto
	 * @throws Exception
	 */
	public void doCashSettle(PublicSettleParamDto publicSettleParamDto) throws Exception {
		PublicSettleResultDto publicSettleResultDto = iCInteract.sendCreditCashSettle(publicSettleParamDto);
		boolean remoteInvocation = getRemoteInvocationResult(publicSettleResultDto);
		if (!remoteInvocation) {
			// 调用接口处理失败
			return;
		}

		CreditDetailDto updateCreditDetailDto = null;
		List<CreditDetailDto> updateList = new ArrayList<CreditDetailDto>();
		List<CreditRedeemSettleDto> settleList = publicSettleParamDto.getListRedeemSettle();
		for (CreditRedeemSettleDto dto : settleList) {
			updateCreditDetailDto = new CreditDetailDto();
			updateCreditDetailDto.setDealCode(dto.getDealCode());
			updateCreditDetailDto.setTransferId(dto.getTransferId());
			updateCreditDetailDto.setSettleApplyId(publicSettleParamDto.getApplyCode());
			updateCreditDetailDto.setCostState(CimsConstant.COST_STATUS_SQ);

			updateList.add(updateCreditDetailDto);
		}
		
		// 修改流水表结算状态和申请编号
		if (CollectionsUtils.isNotEmpty(updateList)) {
			creditRightDao.updateCreditDetailCostInfo(updateList);
		}
	}
	/**
	 * @description 标出该条已经做过虚拟现金流挂账
	 * @param creditDetailDtoList
	 */
	@Transactional(propagation = Propagation.REQUIRES_NEW, timeout = 30)
	public void stampCreditDetailInferfaceNo(List<CreditDetailDto> creditDetailDtoList) {
		creditRightDao.updateCreditDetailInferfaceNo(creditDetailDtoList);
	}

	/**
	 * @description getRemoteInvocationResult
	 * @param publicSettleResultDto
	 * @return true:成功；false:失败
	 */
	private boolean getRemoteInvocationResult(PublicSettleResultDto publicSettleResultDto) {
		if (null == publicSettleResultDto) {
			return false;
		} else {
			if (!CimsConstant.RET_CODE_SUC.equals(publicSettleResultDto.getRetCode())) {
				return false;
			}
		}
		return true;
	}

	/**
	 * @description 验证交易类型
	 * @param dealType
	 *            交易类型
	 * @return 错误信息
	 */
	private String checkDealType(final String dealType) {
		logger.info("交易类型:::" + dealType);
		if (!SimpleStringUtils.hasText(dealType)) {
			return "交易类型为空！";
		}
		String[] dealTypes = { CimsConstant.DEAL_TYPE_MONTH_BACK, CimsConstant.DEAL_TYPE_CREDIT_SETTLE, CimsConstant.DEAL_TYPE_LOAN_MONTH_BACK,
				CimsConstant.DEAL_TYPE_LOAN_CREDIT_SETTLE, CimsConstant.DEAL_TYPE_CREDIT_NORMAL_SETTLE_REC,
				CimsConstant.DEAL_TYPE_CREDIT_ABNORMAL_SETTLE_REC };
		for (String str : dealTypes) {
			if (str.equals(dealType)) {
				return null;
			}
		}
		return "交易类型的值[" + dealType + "]错误！";
	}

	/**
	 * @description 验证输入的结算参数
	 * @param creditDetailQueryDto
	 */
	private void checkSettleParams(CreditDetailQueryDto creditDetailQueryDto) {
		// 结算债权业务打印参数
		logger.info("正常结算/异常结算参数  begin");
		logger.info("交易类型==>>:::" + creditDetailQueryDto.getDealType());
		logger.info("合作机构编号==>>:::" + creditDetailQueryDto.getCooperorgCode());
		logger.info("合约编号==>>:::" + creditDetailQueryDto.getContractCode());
		logger.info("所属包编号==>>:::" + creditDetailQueryDto.getPackageNum());
		logger.info("结算日期==>>:::" + creditDetailQueryDto.getSettleDate());
		logger.info("协议编号==>>:::" + creditDetailQueryDto.getAgreementCode());
		logger.info("多个还款计划状态==>>:::" + creditDetailQueryDto.getPlanStatusList());
		logger.info("一个还款计划状态==>>:::" + creditDetailQueryDto.getPlanStatus());
		logger.info("正常结算/异常结算参数  end");

		String dealType = creditDetailQueryDto.getDealType();// 交易类型
		// 验证交易类型
		String errors = checkDealType(dealType);
		if (SimpleStringUtils.hasText(errors)) {
			throw new CimsException(errors);
		}

		List<String> planStatusList = creditDetailQueryDto.getPlanStatusList();
		// 如果异常结算，设置异常结算类型
		if ((CimsConstant.DEAL_TYPE_CREDIT_SETTLE.equals(dealType) || CimsConstant.DEAL_TYPE_LOAN_CREDIT_SETTLE.equals(dealType) || CimsConstant.DEAL_TYPE_CREDIT_ABNORMAL_SETTLE_REC
				.equals(dealType)) && CollectionsUtils.isNotEmpty(planStatusList)) {
			if (planStatusList.size() == 1) {
				creditDetailQueryDto.setPlanStatus(planStatusList.get(0));
			}
		}

		// 如果协议编码为空，根据合约编号获取协议编号
		if (!SimpleStringUtils.hasText(creditDetailQueryDto.getAgreementCode())) {
			TCMmContractDTO tcmmContractDTO = new TCMmContractDTO();
			tcmmContractDTO.setContractCode(creditDetailQueryDto.getContractCode());
			List<TCMmContractDTO> tcmmContractList = tcmmContractDao.searchTCMmContract(SearchParamUtil.getSearchParam(tcmmContractDTO));
			if (CollectionsUtils.isNotEmpty(tcmmContractList)) {
				creditDetailQueryDto.setAgreementCode(tcmmContractList.get(0).getAgreementCode());
			}
		}
	}

	/**
	 * @description 转换
	 * @param list
	 * @return
	 */
	private List<CreditDetailDto> tranCreditDetailList(List<CreditDetailDto> creditDetailList) {
		List<CreditDetailDto> result = new ArrayList<CreditDetailDto>();
		for (CreditDetailDto creditDetailDto : creditDetailList) {
			creditDetailDto = tranCreditDetail(creditDetailDto);
			result.add(creditDetailDto);
		}
		return result;
	}

	/**
	 * @description 转换
	 * 
	 * @param creditDetailList
	 * @param costPlanList
	 * @return
	 */
	public List<CreditDetailDto> tranCreditDetailList(List<CreditDetailDto> creditDetailList, List<TCMmCostPlanDTO> costPlanList) {
		List<CreditDetailDto> result = new ArrayList<CreditDetailDto>();
		Map<String, Object> searchParams = new HashMap<String, Object>();
		
		for (CreditDetailDto creditDetailDto : creditDetailList) {
			String creditCode = creditDetailDto.getCreditCode();
			String transferId = creditDetailDto.getTransferId();
			for (TCMmCostPlanDTO costPlan : costPlanList) {
				if (creditCode.equals(costPlan.getCreditorCode()) && transferId.equals(costPlan.getTransferId())) {
					creditDetailDto.setCurrentTime(costPlan.getCurrentTime()); // 当前还款期数
					creditDetailDto.setSettleDate(costPlan.getStartDate()); // 结算日期

					// 2016-10-26 add
					searchParams.clear();
					searchParams.put("dto", costPlan);
					TCMmCostPlanDTO costPlan2 = costPlanDao.searchTCMmCostPlanMustAmount(searchParams);
					BigDecimal mustAmountTotal = BigDecimal.ZERO;
					if(costPlan2!=null){
						mustAmountTotal = costPlan2.getMustAmountTotal() != null ? costPlan2.getMustAmountTotal() : BigDecimal.ZERO; // 剩余本金之和
					}
					BigDecimal settleValueBefore = mustAmountTotal.add(costPlan.getThisRepaySum()); // 提前结清价值=剩余期数的本金之和+当前一期应付月还金额；
					creditDetailDto.setMustAmountTotal(mustAmountTotal);
					creditDetailDto.setSettleValueBefore(settleValueBefore);
				}
			}
			result.add(creditDetailDto);
		}
		
		searchParams.clear();
		return result;
	}

	/**
	 * @description 翻译转换中文
	 * @param creditDetailDto
	 * @return
	 */
	private CreditDetailDto tranCreditDetail(CreditDetailDto creditDetailDto) {
		creditDetailDto.setSex(dealService.getDictDetailName("SEX", creditDetailDto.getSex()));// 性别
		creditDetailDto.setCardType(dealService.getDictDetailName("IDTYPE", creditDetailDto.getCardType()));// 证件类型
		creditDetailDto.setDiploma(dealService.getDictDetailName("EDUCATION", creditDetailDto.getDiploma()));// 学历
		creditDetailDto.setDuty(dealService.getDictDetailName("DUTY", creditDetailDto.getDuty()));
		creditDetailDto.setIsHasHouse(dealService.getDictDetailName("HOUSETYPE", creditDetailDto.getIsHasHouse()));
		creditDetailDto.setMarryStatus(dealService.getDictDetailName("MARITALSTATUS", creditDetailDto.getMarryStatus()));
		creditDetailDto.setIsHasChild(dealService.getDictDetailName("CHILDSTATUS", creditDetailDto.getIsHasChild()));
		creditDetailDto.setCompanyType(dealService.getDictDetailName("JOBNATURE", creditDetailDto.getCompanyType()));
		creditDetailDto.setHouseholdType(dealService.getDictDetailName("CENSUSTYPE", creditDetailDto.getHouseholdType()));
		creditDetailDto.setCreditorStatus(dealService.getDictDetailName("creditorStatus", creditDetailDto.getCreditorStatus()));
		creditDetailDto.setBorrowerUse(dealService.getDictDetailName("LOANPURPOSE", creditDetailDto.getBorrowerUse()));
		return creditDetailDto;
	}

	/**
	 * @description 填充债权交易明细
	 * @param creditDetailList
	 * @param params
	 * @return
	 */
	private List<TCMmCreditDealDetailDTO> getCreditDealDetailList(final List<CreditDetailDto> creditDetailList, final CreditDetailQueryDto params) {
		TCMmCreditDealDetailDTO creditDealDetail = null;
		List<TCMmCreditDealDetailDTO> creditDealDetailList = new ArrayList<TCMmCreditDealDetailDTO>();
		for (CreditDetailDto creditDetail : creditDetailList) {
			creditDealDetail = new TCMmCreditDealDetailDTO();
			creditDealDetail.setDealStreamCode(params.getDealCode());// 交易流水号
			creditDealDetail.setAgreementCode(params.getAgreementCode());// 协议编号
			creditDealDetail.setTransferId(creditDetail.getTransferId());// 转让编号
			creditDealDetail.setCreditorId(creditDetail.getCreditCode());// 债权编号
			creditDealDetail.setCooperorgCode(params.getCooperorgCode());// 转让合作机构编号
			creditDealDetail.setCreditorStatus(CimsConstant.CREDIT_STATUS_WAY);// 债权状态
			creditDealDetail.setMakeCreditorValue(creditDetail.getMakeCreditorValue());// 转让债权价值
			creditDealDetail.setDeliverDate(creditDetail.getDeliverDate());// 交割日期
			creditDealDetail.setThisMakeCreditorValue(creditDetail.getThisMakeCreditorValue());// 本次转让债权价值
			creditDealDetail.setThisRepaySum(creditDetail.getThisRepaySum());// 本期还款金额
			creditDealDetail.setRepayPeriod(creditDetail.getRepayPeriod());// 还款期数
			creditDealDetail.setThisCreditorValue(creditDetail.getThisCreditorValue());// 当前债权价值
			creditDealDetail.setCreateTime(new Timestamp(System.currentTimeMillis()));// 创建时间
			creditDealDetail.setCreateBy(creditDetail.getCreateUserNameExt());

			creditDealDetailList.add(creditDealDetail);
		}

		return creditDealDetailList;
	}

	/**
	 * @description 填充合作机构交易流水表
	 * @param creditDetailList
	 * @param params
	 * @param creditSettleInfoDto
	 * @return
	 */
	private DealDto getDealDto(final List<CreditDetailDto> creditDetailList, final CreditDetailQueryDto params,
			final CreditSettleInfoDto creditSettleInfoDto) {
		String dealType = params.getDealType();// 交易类型
		DealDto dealDto = new DealDto();
		CreditDetailDto creditDetail = creditDetailList.get(0);
		dealDto.setDealCode(params.getDealCode());// 交易流水号
		dealDto.setContractCode(params.getContractCode());// 合约编号
		dealDto.setAgreementCode(params.getAgreementCode());// 协议编号
		dealDto.setCooperorgCode(params.getCooperorgCode());// 合作机构
		dealDto.setDealDate(new java.util.Date());// 交易日期
		dealDto.setDealType(dealType);// 交易类型
		if (params.getPracticalSellSum().compareTo(BigDecimal.ZERO) == 1) {
			dealDto.setCooperativeAgencyDealStatus(CimsConstant.DEAL_STATUS_MONTH_BACK);// 合作机构交易状态:04-待购买
		} else {
			dealDto.setCooperativeAgencyDealStatus(CimsConstant.DEAL_STATUS_SECOND_PURCHASE);// 合作机构交易状态:05-已购买
		}
		dealDto.setDetialNumber(creditDetailList.size());// 明细数目
		dealDto.setCreateBy(creditDetail.getCreateUserNameExt());// 创建人
		dealDto.setCreateTime(new Timestamp(System.currentTimeMillis()));// 创建时间
		dealDto.setBillDate(params.getBillDate());// 账单日
		dealDto.setCreditPackageName(params.getPackageNum());// 债权包名称
		dealDto.setPlanSellSum(creditSettleInfoDto.getMatchAmount());// 预售金额=应匹配金额
		dealDto.setPracticalSellSum(params.getPracticalSellSum());// 实售金额=实际匹配金额， 默认等于应匹配金额，页面可以手动修改的 实际匹配金额
		dealDto.setSumCreditorValue(creditSettleInfoDto.getThisRepaySum());// 本期还款金额
		dealDto.setDeliverSum(creditSettleInfoDto.getReturnAmount());// 应返还金额
		// 异常结算设置异常类型
		if (CimsConstant.DEAL_TYPE_CREDIT_SETTLE.equals(dealType) || CimsConstant.DEAL_TYPE_LOAN_CREDIT_SETTLE.equals(dealType)
				|| CimsConstant.DEAL_TYPE_CREDIT_ABNORMAL_SETTLE_REC.equals(dealType)) {
			dealDto.setAbnormalSettleType(params.getPlanStatus());
		}
		dealDto.setSettleDate(DateTimeUtils.parse(params.getSettleDate(), DateTimeUtils.DEFAULT_DATE_FORMAT_2));

		return dealDto;
	}
}